#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define USER_MAX 10000
#define SERVER_PORT 12345
#define SERVER_IP 	"192.168.56.101"
#define RANK_COUNT 10

typedef struct User
{
	uint32_t score;
	char name[20];
}User;

User* users;
size_t user_cnt;
int sock;

// 通用的二进制文件保存
int save_data(void *base, uint32_t size, uint32_t nmemb, const char *path)
{
	assert(NULL != base && NULL != path);

	FILE *wfp = fopen(path, "w");
	if (NULL == wfp)
	{
		printf("%s %m\n", path);
		return 0;
	}

	int cnt = fwrite(base, size, nmemb, wfp);
	fclose(wfp);
	return cnt;
}

// 通用的二进制文件读取
int load_data(void *base, uint32_t size, uint32_t nmemb, const char *path)
{
	assert(NULL != base && NULL != path);

	FILE *rfp = fopen(path, "r");
	if (NULL == rfp)
	{
		printf("%s %m\n", path);
		return 0;
	}

	int cnt = fread(base, size, nmemb, rfp);
	fclose(rfp);
	return cnt;
}

// 根据成绩进行插入排序
int user_sort(const User* user)
{
	for(int i=user_cnt-1; i>=0; i--)
	{
		if(users[i].score < user->score)
		{
			users[i+1] = users[i];
		}
		else
		{
			users[i+1] = *user;
			user_cnt++;
			return i+1;
		}
	}

	user_cnt++;
	users[0] = *user;
	return 0;
}

void init_game2048(void)
{
	// 申请内存
	users = malloc(sizeof(User)*USER_MAX);
	if(NULL == users)
	{
		perror("malloc");
		return;
	}
	

	// 加载数据
	user_cnt = load_data(users,sizeof(User),USER_MAX,"user.dat");

	// 创建socket对象
	sock = socket(AF_INET,SOCK_DGRAM,0);
	if(0 > sock)
	{
		perror("socket");
		return;
	}

	// 准备通信地址
	struct sockaddr_in addr = {};
	addr.sin_family = AF_INET;
	addr.sin_port = htons(SERVER_PORT);
	addr.sin_addr.s_addr = inet_addr(SERVER_IP);
	socklen_t addrlen = sizeof(addr);

	// 绑定socket对象和通信地址
	if(bind(sock,(struct sockaddr*)&addr,addrlen))
	{
		perror("bind");
	}
}

void start_game2048(void)
{
	User user;
	char buf[4096];
	size_t buf_size = sizeof(buf);
	struct sockaddr_in src_addr;
	socklen_t addrlen = sizeof(src_addr);

	for(;;)
	{
		// 接收成绩
		recvfrom(sock,buf,buf_size,0,
				(struct sockaddr*)&src_addr,&addrlen);

		sscanf(buf,"score:%u name:%s",&user.score,user.name);
		printf("score:%u name:%s\n",user.score,user.name);

		// 排序
		int rank = user_sort(&user);

		sprintf(buf,"%u",rank+1);
		printf("rank = %u\n",rank+1);
		
		// 返回排序结果
		sendto(sock,buf,strlen(buf)+1,0,
				(struct sockaddr*)&src_addr,addrlen);

		// 返回前n名成绩
		for(int i=0; i<RANK_COUNT; i++)
		{
			sprintf(buf,"top:%03d %s score:%u",i+1,users[i].name,users[i].score);
			sendto(sock,buf,strlen(buf)+1,0,
				(struct sockaddr*)&src_addr,addrlen);
		}
	}
}

void exit_game2048(void)
{
	// 关闭socket
	close(sock);

	// 保存数据
	save_data(users,sizeof(User),user_cnt,"user.dat");

	// 释放内存
	free(users);
}

void sigint(int signum)
{
	exit_game2048();
	exit(0);
}

int main(int argc,const char* argv[])
{
	signal(SIGINT,sigint);

	init_game2048();

	start_game2048();
	/*
	User users[1000];
	for(int i=999; i>=0; i--)
	{
		sprintf(users[i].name,"test%d",i+1);
		users[i].score = (999-i+1)*4;
		printf("%s %u\n",users[i].name,users[i].score);
	}

	save_data(users,sizeof(User),1000,"user.dat");

	*/

	return 0;
}
